/*!
 * \file BitMapDirectlyAddressedSets.cpp
 *
 * \date Nov 14, 2012
 * \author correa
 */

#include "BitMapDirectlyAddressedSets.h"

template<typename T>
void BitMapDirectlyAddressedSets<T>::unionOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, ArrayBitMapDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;
	T * iu;
	for (anode = a->arrayNode(0), bnode = b->arrayNode(0), rnode = res->arrayNode(0), iu = anode + a->quotient(a->universeSize()); anode < iu; anode++, bnode++, rnode++)
		*rnode = *anode | *bnode;
	long rem = a->remainder(a->universeSize());
	if (rem > 0)
		*rnode |= ~BitTools<T>::__mask[rem] & (*anode | *bnode);
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::unionOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, MultiLevelDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;

	DirectlyAddressedSet::Iterator * bit = b->newIterator(b->height()-1);
	long inode = bit->next();
	long iu = b->level[1]->universeSize()-1;
	while (inode < iu) {
		anode = a->arrayNode(inode);
		bnode = b->arrayNode(inode);
		rnode = res->arrayNode(inode);
		*rnode = *anode | *bnode;
		inode = bit->next();
	}
	anode = a->arrayNode(inode);
	bnode = b->arrayNode(inode);
	rnode = res->arrayNode(inode);
	iu = b->remainder(b->universeSize());
	if (iu > 0)
		*rnode |= ~BitTools<T>::__mask[iu] & (*anode | *bnode);
	else
		*rnode = *anode | *bnode;
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::intersectOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, ArrayBitMapDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;
	T * iu;
	for (anode = a->arrayNode(0), bnode = b->arrayNode(0), rnode = res->arrayNode(0), iu = anode + a->quotient(a->universeSize()); anode < iu; anode++, bnode++, rnode++)
		*rnode = *anode & *bnode;
	long rem = a->remainder(a->universeSize());
	if (rem > 0)
		*rnode |= ~BitTools<T>::__mask[rem] & (*anode & *bnode);
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::intersectOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, MultiLevelDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;
	T * snode;

	DirectlyAddressedSet::Iterator * bit = b->newIterator(b->height()-1);
	snode = res->arrayNode(0);
	long inode = bit->next();
	long iu = b->level[1]->universeSize();
	while (inode < iu-1) {
		anode = a->arrayNode(inode);
		bnode = b->arrayNode(inode);
		rnode = res->arrayNode(inode);
		while (snode < rnode) {
			*snode = 0x00;
			snode++;
		}
		*rnode = *anode & *bnode;
		inode = bit->next();
	}
	anode = a->arrayNode(iu-1);
	bnode = b->arrayNode(iu-1);
	rnode = res->arrayNode(iu-1);
	while (snode < rnode) {
		*snode = 0x00;
		snode++;
	}
	iu = b->remainder(b->universeSize());
	if (iu > 0)
		*rnode |= ~BitTools<T>::__mask[iu] & (*anode & *bnode);
	else
		*rnode = *anode & *bnode;
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::symDiffOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, ArrayBitMapDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;
	T * iu;
	for (anode = a->arrayNode(0), bnode = b->arrayNode(0), rnode = res->arrayNode(0), iu = anode + a->quotient(a->universeSize()); anode < iu; anode++, bnode++, rnode++)
		*rnode = *anode ^ *bnode;
	long rem = a->remainder(a->universeSize());
	if (rem > 0)
		*rnode |= ~BitTools<T>::__mask[rem] & (*anode ^ *bnode);
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::symDiffOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, MultiLevelDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;

	DirectlyAddressedSet::Iterator * bit = b->newIterator(b->height()-1);
	long inode = bit->next();
	long iu = b->level[1]->universeSize()-1;
	while (inode < iu) {
		anode = a->arrayNode(inode);
		bnode = b->arrayNode(inode);
		rnode = res->arrayNode(inode);
		*rnode = *anode ^ *bnode;
		inode = bit->next();
	}
	anode = a->arrayNode(inode);
	bnode = b->arrayNode(inode);
	rnode = res->arrayNode(inode);
	iu = b->remainder(b->universeSize());
	if (iu > 0)
		*rnode |= ~BitTools<T>::__mask[iu] & (*anode ^ *bnode);
	else
		*rnode = *anode ^ *bnode;
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::diffOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, ArrayBitMapDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;
	T * iu;
	for (anode = a->arrayNode(0), bnode = b->arrayNode(0), rnode = res->arrayNode(0), iu = anode + a->quotient(a->universeSize()); anode < iu; anode++, bnode++, rnode++)
		*rnode = *anode & ~*bnode;
	long rem = a->remainder(a->universeSize());
	if (rem > 0)
		*rnode |= ~BitTools<T>::__mask[rem] & (*anode & ~*bnode);
}

template<typename T>
void BitMapDirectlyAddressedSets<T>::diffOf(ArrayBitMapDirectlyAddressedSet<T>* res, ArrayBitMapDirectlyAddressedSet<T>* a, MultiLevelDirectlyAddressedSet<T>* b) {
	T * anode;
	T * bnode;
	T * rnode;

	DirectlyAddressedSet::Iterator * bit = b->newIterator(b->height()-1);
	long inode = bit->next();
	long iu = b->level[1]->universeSize()-1;
	while (inode < iu) {
		anode = a->arrayNode(inode);
		bnode = b->arrayNode(inode);
		rnode = res->arrayNode(inode);
		*rnode = *anode & ~*bnode;
		inode = bit->next();
	}
	anode = a->arrayNode(inode);
	bnode = b->arrayNode(inode);
	rnode = res->arrayNode(inode);
	iu = b->remainder(b->universeSize());
	if (iu > 0)
		*rnode |= ~BitTools<T>::__mask[iu] & (*anode & ~*bnode);
	else
		*rnode = *anode & ~*bnode;
}

